package morning.cat.curator.sample;

import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

/**
 * XXX
 *
 * @author mengzhang6
 * @date 2018/11/30 10:02
 */
public class CuratorClientSample {

    private String zkServices;
    private CuratorFramework client = null;
    private static final int DEFAULT_SESSION_TIMEOUT_MS = Integer.getInteger("session超时时间默认值", 60 * 1000);
    private static final int DEFAULT_CONNECTION_TIMEOUT_MS = Integer.getInteger("连接超时时间默认值", 15 * 1000);

    public CuratorClientSample(String zkServices) {
        this.zkServices = zkServices;
    }

    public void init() {
        if (StringUtils.isEmpty(zkServices)) {
            throw new IllegalArgumentException("没有配置zk服务地址...");
        }
        /**
         * 重试使用策略
         *
         * @param baseSleepTimeMs initial amount of time to wait between retries
         * @param maxRetries max number of times to retry
         * @param maxSleepMs max time in ms to sleep on each retry
         */
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3, Integer.MAX_VALUE);
        /**
         * Create a new client
         *
         * @param connectString       list2 of servers to connect to
         * @param sessionTimeoutMs    session timeout
         * @param connectionTimeoutMs connection timeout
         * @param retryPolicy         retry policy to use
         * @return client
         */
        client = CuratorFrameworkFactory.newClient(zkServices, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, retryPolicy);
        client.start();
    }

    public void destroy() {
        client.close();
    }

    public String createNodeForBytes(String path, byte[] content, CreateMode createMode) throws Exception {
        String result = null;
        if (createMode == null) {
            //默认永久节点
            createMode = CreateMode.PERSISTENT;
        }
        if (path == null) {
            throw new IllegalArgumentException("存储路径不能为null");
        }
        if (checkNodeExists(path)) {
            //deleteNode(path);
            return path;
        }

        switch (createMode) {
            case PERSISTENT:
                //永久节点
                result = client.create()
                        .creatingParentContainersIfNeeded()
                        .withMode(CreateMode.PERSISTENT)
                        .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                        .forPath(path, content);
                break;
            case EPHEMERAL:
                //临时节点
                result = client.create().withMode(CreateMode.EPHEMERAL).forPath(path, content);
                break;
            default:
                break;
        }
        return result;

    }

    public String createNode(String path, String content, CreateMode createMode) throws Exception {
        if (content == null) {
            return createNodeForBytes(path, null, createMode);
        }
        return createNodeForBytes(path, content.getBytes(), createMode);
    }

    public String getValue(String path) throws Exception {
        if (checkNodeExists(path)) {
            byte[] bytes = client.getData().forPath(path);
            if (bytes == null) {
                return null;
            }
            return new String(bytes);
        }
        return null;
    }

    public Object setValue(String path, String value) throws Exception {
        if (value == null) {
            return client.setData().inBackground().forPath(path, null);
        }
        return client.setData().inBackground().forPath(path, value.getBytes());
    }


    public Boolean checkNodeExists(String path) throws Exception {
        Stat stat = client.checkExists().forPath(path);
        if (stat == null) {
            return false;
        }
        return true;
    }

    public void deleteNode(String path) throws Exception {
        client.delete().deletingChildrenIfNeeded().forPath(path);
    }

}
